﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace d39
{
    public static class Initiative
    {
        private static Random random = new Random();
        public static int RollD20()
        {
            return random.Next(1, 21);
        }
        private static void addInitRoll(this Player player)
        {
            if (player.InitiativeMod == null) throw new ArgumentException(player.Name + " does not have an initiative modifier");
            player.Initiative.Add(RollD20() + (int)player.InitiativeMod);
        }

        public static bool InitiativeApplicable(this List<Player> players)
        {
            return players.Any(p => p.isInInitOrder());
        }

        public static void RollInitiative(this List<Player> players)
        {
            foreach (var player in players) player.Initiative.Clear();
            var withInitiative = players.Where(p => p.isInInitOrder()).ToList();
            var withoutInitiative = players.Where(p => !p.isInInitOrder()).ToList();
            withInitiative.Sort(new InitiativeComparer());
            players.Clear();
            players.AddRange(withInitiative);
            players.AddRange(withoutInitiative);
        }

        private static bool isInInitOrder(this Player player)
        {
            return player.InitiativeMod != null && !player.IsFixed && !player.IsAllInactive;
        }

        private class InitiativeComparer : Comparer<Player>
        {
            public override int Compare(Player p1, Player p2)
            {
                if (object.ReferenceEquals(p1, p2)) return 0;

                var result = compareInitiativeAtIndex(0, p1, p2);
                if (result == 0) result = ((int)p1.InitiativeMod).CompareTo((int)p2.InitiativeMod);

                int index = 1;
                while (result == 0) result = compareInitiativeAtIndex(index++, p1, p2);

                return -result;
            }

            private int compareInitiativeAtIndex(int index, Player p1, Player p2)
            {
                if (p1.Initiative.Count < index || p2.Initiative.Count < index) throw new ArgumentException("compareInitiativeAtIndex requires initiatives to already have been compared up to index-1");
                if (p1.Initiative.Count == index) p1.addInitRoll();
                if (p2.Initiative.Count == index) p2.addInitRoll();
                return p1.Initiative[index].CompareTo(p2.Initiative[index]);
            }
        }
    }
}